package com.ecr.hub.front.bean.managed;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.ecr.hub.ApplicationException;
import com.ecr.hub.RailDestinationException;
import com.ecr.hub.front.bean.AbstractManagedBean;
import com.ecr.hub.model.destination.Destination;
import com.ecr.hub.service.destination.IDestinationManager;
import com.ecr.hub.service.destination.IDestinationRailTranscoder;
import com.ecr.hub.util.MessageUtils;

@Controller("destinationManaged")
@Scope("session")
public class DestinationManagedBean extends AbstractManagedBean {

	private static final long serialVersionUID = 1L;

	private List<Destination> lstDestinations;
	private int currentDestinationIndex;
	private Destination currentDestination;

	// Ressource pour les destinations.
	@Resource(name = "destinationManager")
	private transient IDestinationManager destinationManager;

	// Ressource pour la liste des transcos rail / destination.
	@Resource(name = "destinationRailTranscoder")
	private transient IDestinationRailTranscoder destinationRailTranscoder;

	// *******************************
	// Les méthodes.
	// *******************************

	/**
	 * Chargement de l'ensemble des code gares.
	 */
	@PostConstruct
	public void _getAllDestinations() {
		try {
			setLstDestinations(destinationManager.getAllList());
		} catch (Exception e) {
			getErrorHandler(e);
		}
	}

	/**
	 * Suppression de la destination dans la base de données. La destination
	 * courante est directement supprimée dans la liste, cela évite de faire un
	 * select pour rafraîchir la liste des destinations. On demande le
	 * rafraichissement complet du bean contenant les listes déroulantes, de
	 * celui contenant les voies, et le rafraichissement du bean de contrôle du
	 * hub. Il est impossible de supprimer une destination si cette dernière est
	 * attachée à une voie. Il faut en premier lieu la dettacher de la voie.
	 */
	public void delete() {

		try {
			destinationManager.delete(lstDestinations
					.get(currentDestinationIndex));
			lstDestinations.remove(currentDestinationIndex);
			MessageUtils.setMessageInfo("destination.deleted");
			destinationRailTranscoder.refresh();
			RepositoryManagedBean.refresh();
			RailManagedBean.refresh();
			HubManagedBean.refresh();
			// TODO : contrôle sur attachement voie.
		} catch (RailDestinationException e) {
			MessageUtils.setMessageError("destination.delete.refused");
		} catch (Exception e) {
			getErrorHandler(e);
		}
	}

	/**
	 * Edition de la destination, soit en insertion, soit en modification, dans
	 * les deux cas, la destination courante est replacée dans la liste après
	 * opération en base de données, cela évite de faire un select pour
	 * rafraîchir la liste des destinations.On demande le rafraichissement
	 * complet du bean contenant les listes déroulantes, de celui contenant la
	 * liste des voies, et le rafraichissement du bean contenant le hub.
	 * 
	 * @throws ApplicationException
	 */
	public void edit() {

		try {
			// Insertion ou modification utilisateur.
			if ("update".equals(typeAction)) {

				destinationManager.update(currentDestination);
				lstDestinations
						.set(currentDestinationIndex, currentDestination);
				MessageUtils.setMessageInfo("destination.modified");

			} else if ("create".equals(typeAction)) {

				destinationManager.create(currentDestination);
				lstDestinations.add(currentDestination);
				MessageUtils.setMessageInfo("destination.created");
			}
			destinationRailTranscoder.refresh();
			RepositoryManagedBean.refresh();
			RailManagedBean.refresh();
			HubManagedBean.refresh();
		} catch (Exception e) {
			getErrorHandler(e);
		}
	}

	/**
	 * Validator interne au bean. Vérification du code gare, ce dernier doit
	 * être unique en base de données.
	 */
	public void destinationUniqueValidator(FacesContext context,
			UIComponent component, Object value) throws ValidatorException {
		for (Destination dest : lstDestinations) {
			if ((dest.getId() != currentDestination.getId())
					&& (dest.getExtId().equals(value))) {
				throw new ValidatorException(
						MessageUtils
								.getMessageError("validator.code.station.notunique"));

			}
		}
	}

	// ********************************
	// Les getters et les setters.
	// ********************************

	public List<Destination> getLstDestinations() {
		return lstDestinations;
	}

	public void setLstDestinations(List<Destination> lstDestinations) {
		this.lstDestinations = lstDestinations;
	}

	public int getCurrentDestinationIndex() {
		return currentDestinationIndex;
	}

	public Destination getCurrentDestination() {
		return currentDestination;
	}

	public void setCurrentDestinationIndex(int currentDestinationIndex) {
		this.currentDestinationIndex = currentDestinationIndex;
	}

	public void setCurrentDestination(Destination currentDestination) {
		this.currentDestination = currentDestination;
	}

	@Override
	public void setTypeAction(String typeAction) {
		if ("create".equals(typeAction))
			setCurrentDestination(new Destination());
		this.typeAction = typeAction;
	}
}
